package edu.northwestern.cbits.purple_robot_manager.probes;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import edu.northwestern.cbits.purple_robot_manager.R;
import edu.northwestern.cbits.purple_robot_manager.activities.settings.FlexibleListPreference;
import edu.northwestern.cbits.purple_robot_manager.logging.LogManager;
public abstract class Probe
{
public static final String PROBE_READING = "edu.northwestern.cbits.purple_robot.PROBE_READING";
public static final String PROBE_TRANSMIT_BUFFER = "edu.northwestern.cbits.purple_robot.PROBE_TRANSMIT_BUFFER";
public static final String PROBE_CALIBRATION_NOTIFICATIONS = "enable_calibration_notifications";
public static final String PROBE_FREQUENCY = "frequency";
public static final String PROBE_SAMPLE_FREQUENCY = "sample_frequency";
public static final String HASH_DATA = "hash_data";
public static final String DEFAULT_FREQUENCY = "300000";
public static final boolean DEFAULT_HASH_DATA = true;
public static final String ENCRYPT_DATA = "encrypt_data";
public static final String PROBE_ENABLED = "enabled";
public static final String PROBE_NAME = "name";
protected static final String BUNDLE_PROBE = "PROBE";
protected static final String BUNDLE_TIMESTAMP = "TIMESTAMP";
public static final String PROBE_TYPE_LONG = "long";
public static final String PROBE_TYPE_BOOLEAN = "boolean";
public static final String PROBE_TYPE_DOUBLE = "double";
public static final String PROBE_TYPE_STRING = "string";
public static final String PROBE_TYPE = "type";
public static final String PROBE_VALUES = "values";
public static final String PROBE_DISTANCE = "distance";
public static final String PROBE_DURATION = "duration";
public static final String PROBE_MEDIA_URL = "media_url";
public static final String PROBE_MEDIA_CONTENT_TYPE = "media_content_type";
public static final String PROBE_MEDIA_SIZE = "media_size";
public static final String PROBE_MUTE_WARNING = "mute_warning";
public static final String PROBE_GUID = "GUID";
public static final String PROBE_DATA = "PROBE_DATA";
public static final String PROBE_DISPLAY_NAME = "PROBE_DISPLAY_NAME";
public static final String PROBE_DISPLAY_MESSAGE = "PROBE_DISPLAY_MESSAGE";
public static final String PROBE_TRANSMIT_MODE = "PROBE_TRANSMIT_MODE";
public static final int PROBE_TRANSMIT_MODE_NORMAL = 0;
public static final int PROBE_TRANSMIT_MODE_PRIORITY = 1;
public static final int PROBE_TRANSMIT_MODE_ON_DEMAND = 2;
private static List<Class<Probe>> _probeClasses = new ArrayList<>();
public abstract String name(Context context);
public abstract String title(Context context);
public abstract String probeCategory(Context context);
public PreferenceScreen preferenceScreen(Context context, PreferenceManager manager)
{
PreferenceScreen screen = manager.createPreferenceScreen(context);
FlexibleListPreference threshold = new FlexibleListPreference(context);
threshold.setKey("config_" + this.getPreferenceKey() + "_transmit_mode");
threshold.setDefaultValue("" + Probe.PROBE_TRANSMIT_MODE_NORMAL);
threshold.setEntryValues(R.array.probe_transmit_mode_values);
threshold.setEntries(R.array.probe_transmit_mode_labels);
threshold.setTitle(R.string.probe_transmit_mode_label);
threshold.setSummary(R.string.probe_transmit_mode_summary);
screen.addPreference(threshold);
return screen;
}
public abstract String summary(Context context);
private static long _lastEnabledCheck = 0;
private static boolean _lastEnabled = false;
private static SharedPreferences _preferences = null;
public static SharedPreferences getPreferences(Context context)
{
if (Probe._preferences == null)
Probe._preferences = PreferenceManager.getDefaultSharedPreferences(context);
return Probe._preferences;
}
public void nudge(Context context)
{
this.isEnabled(context);
}
@SuppressWarnings("rawtypes")
public static void registerProbeClass(Class probeClass)
{
if (!Probe._probeClasses.contains(probeClass))
Probe._probeClasses.add(probeClass);
}
@SuppressWarnings("rawtypes")
public static List<Class<Probe>> availableProbeClasses()
{
return Probe._probeClasses;
}
public static void loadProbeClasses(Context context)
{
String packageName = Probe.class.getPackage().getName();
String[] probeClasses = context.getResources().getStringArray(R.array.probe_classes);
for (String className : probeClasses)
{
try
{
Probe.registerProbeClass(Class.forName(packageName + "." + className));
}
catch (ClassNotFoundException e)
{
LogManager.getInstance(context).logException(e);
}
}
}
public static boolean probesEnabled(Context context)
{
long now = System.currentTimeMillis();
if (now - Probe._lastEnabledCheck > 10000)
{
Probe._lastEnabledCheck = now;
SharedPreferences prefs = Probe.getPreferences(context);
Probe._lastEnabled = prefs.getBoolean("config_probes_enabled", false);
}
return Probe._lastEnabled;
}
public boolean isEnabled(Context context)
{
long now = System.currentTimeMillis();
if (now - Probe._lastEnabledCheck > 10000)
{
Probe._lastEnabledCheck = now;
SharedPreferences prefs = Probe.getPreferences(context);
Probe._lastEnabled = prefs.getBoolean("config_probes_enabled", false);
}
return Probe._lastEnabled;
}
public String summarizeValue(Context context, Bundle bundle)
{
return bundle.toString();
}
// public abstract void updateFromJSON(Context context, JSONObject json)
// throws JSONException;
public Bundle formattedBundle(Context context, Bundle bundle)
{
Bundle formatted = new Bundle();
if (bundle.containsKey("TIMESTAMP"))
{
try
{
double time = bundle.getDouble("TIMESTAMP");
if (time == 0)
throw new ClassCastException("Catch me.");
Date d = new Date(((long) time) * 1000);
formatted.putString(context.getString(R.string.display_date_recorded), d.toString());
}
catch (ClassCastException e)
{
long time = bundle.getLong("TIMESTAMP");
Date d = new Date(time * 1000);
formatted.putString(context.getString(R.string.display_date_recorded), d.toString());
}
}
return formatted;
}
protected void transmitData(Context context, Bundle data)
{
if (context != null)
{
UUID uuid = UUID.randomUUID();
data.putString(Probe.PROBE_GUID, uuid.toString());
data.putInt(Probe.PROBE_TRANSMIT_MODE, this.getTransmitMode(context));
LocalBroadcastManager localManager = LocalBroadcastManager.getInstance(context);
Intent intent = new Intent(edu.northwestern.cbits.purple_robot_manager.probes.Probe.PROBE_READING);
intent.putExtras(data);
localManager.sendBroadcast(intent);
}
}
public Intent viewIntent(Context context)
{
return null;
}
public String getDisplayContent(Activity activity)
{
return null;
}
public String contentSubtitle(Context context)
{
return null;
}
public abstract void enable(Context context);
public abstract void disable(Context context);
public Map<String, Object> configuration(Context context)
{
HashMap<String, Object> map = new HashMap<>();
map.put("name", this.name(context));
map.put("enabled", this.isEnabled(context));
return map;
}
public void updateFromMap(Context context, Map<String, Object> params)
{
if (params.containsKey(Probe.PROBE_ENABLED))
{
Object enabled = params.get(Probe.PROBE_ENABLED);
if (enabled instanceof Boolean)
{
if ((Boolean) enabled)
this.enable(context);
else
this.disable(context);
}
Object transmitMode = params.get(Probe.PROBE_TRANSMIT_MODE);
if (transmitMode instanceof Integer)
{
int intTransmitMode = (Integer) transmitMode;
if (intTransmitMode < 0 || intTransmitMode > Probe.PROBE_TRANSMIT_MODE_ON_DEMAND)
intTransmitMode = Probe.PROBE_TRANSMIT_MODE_NORMAL;
this.setTransmitMode(context, intTransmitMode);
}
}
}
private void setTransmitMode(Context context, int transmitMode)
{
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
SharedPreferences.Editor e = prefs.edit();
e.putString("config_" + this.getPreferenceKey() + "_transmit_mode", "" + transmitMode);
e.commit();
}
private int getTransmitMode(Context context)
{
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
String transmitMode = prefs.getString("config_" + this.getPreferenceKey() + "_transmit_mode", "" + Probe.PROBE_TRANSMIT_MODE_NORMAL);
return Integer.parseInt(transmitMode);
}
public JSONObject fetchSettings(Context context)
{
JSONObject settings = new JSONObject();
try
{
JSONObject enabled = new JSONObject();
enabled.put(Probe.PROBE_TYPE, Probe.PROBE_TYPE_BOOLEAN);
JSONArray values = new JSONArray();
values.put(true);
values.put(false);
enabled.put(Probe.PROBE_VALUES, values);
settings.put(Probe.PROBE_ENABLED, enabled);
}
catch (JSONException e)
{
LogManager.getInstance(context).logException(e);
}
return settings;
}
public JSONObject fetchSettingsFoo(Context context)
{
// TODO: Make abstract & implement across ALL probes...
return null;
}
public String shortName(Context context)
{
String name = this.name(context);
String[] components = name.split("\\.");
return components[components.length - 1];
}
public String getMainScreenAction(Context context)
{
return null;
}
public void runMainScreenAction(Context context)
{
Log.e("PR", "Unimplemented main screen action for probe " + this.title(context) + "...");
}
public abstract String getPreferenceKey();
// Override in subclasses as documentation is completed...
public String assetPath(Context context)
{
return null;
}
}